/******************************************************
 * Copyright (c) 2012, LIJUN All rights reserved *
 ******************************************************/

/**
 * SmartJS core
 * @author carlli
 * @encode utf-8
 * @version 1.0
 * @data 2012.9.24
 * @modify
 * -------------------------------------------------------------------
 * 
 * -------------------------------------------------------------------
 * @usage
 * -------------------------------------------------------------------
 *
 * -------------------------------------------------------------------
 */

(function(version){
    var Queue = function(){
        this.init();
        this.add.apply(this, arguments);
    };
    
    Queue.prototype = {
        init : function(){
            this.queue = [];
        },
        next : function(){
            return this.queue.shift();
        },
        last : function(){
            return this.queue.pop();
        },
        add : function(){
            var args = arguments;
            var size = args.length;
            var name = "";
            var contextPath = Smart.contextPath;
            
            for(var i = 0; i < size; i++){
                name = args[i].toLowerCase();
                this.queue.push({"name": name, "path" : contextPath + name + Smart.suffix + ".js"});
            }
            return this;
        },
        size : function(){
            return this.queue.length;
        },
        /**
         * 加载脚本
         * @param Object el 元素{String name, String path}
         * @param Function fn 加载队列后回调函数
         */
        require : function(el, fn){
            var mid = "smart_module_" + el.name;
            var node = document.getElementById(mid);
            var script = (null == node ? document.createElement("script") : node);
            
            var heads = document.getElementsByTagName("head");
            var head = (heads && heads.length > 0 ? heads[0] : document.body);
            var eventType = (undefined !== script.onreadystatechange && undefined !== script.readyState) ? "onreadystatechange" : "onload";
            var _queue = this;
            
            script[eventType] = function(){
                var state = script.readyState || "loaded";
                var isLoaded = false;
                if("loaded" == state || "complete" == state){
                    if(!isLoaded){
                        isLoaded = true;
                        _queue.load(fn);
                    }
                }
            };
            script.id = mid;
            script.charset = "utf-8";
            script.async = true;
            script.src = el.path + "?v=" + version;
            
            if(null == node){
                head.appendChild(script);
            }
        },
        load : function(fn){            
            var el = this.next();
            if(undefined !== el){
                this.require(el, fn);
            }else{
                if((fn instanceof Function) && fn.apply){
                    fn.apply(Smart, [Smart]);
                }
            }
        }
    };
    
    var _removeEmpty = function(list){
        var tmp = [];
        for(var i = 0, len = list.length; i < len; i++){
            if(list[i]){
                tmp.push(list[i]);
            }
        }
        return tmp;
    };
    
    var _requires = function(args){
        var size = args.length;
        var modules = [];
        for(var i = 0; i < size - 1; i++){
            modules = ((function(m, list){
                var requires = Smart["Modules"][m].requires || [];
                var l = requires.length;
                var tmp = "|" + list.join("|") + "|";
                tmp = tmp.replace("|" + m + "|", "|");
                tmp = tmp.substr(1, tmp.length - 2);
                list = tmp.split("|");

                list.unshift(m);
                list = _removeEmpty(list);

                if(l > 0){
                    for(var j = 0; j < l; j++){
                        list = arguments.callee(requires[j], list);
                    }
                    return list;
                }else{
                    return list;
                }
            })(args[i], modules));
        }
        return modules;
    };
    
    /**
     * 添加属性和方法
     */
    var proto = {        
        version : version, //版本号
        contextPath : "", //上下文部署路径
        suffix : "", //后缀
        /**
         * 初始化Smart
         */
        init : function(){                        
            this.setContextPath();
            this.source("version", this.version);
            this.source("contextPath", this.contextPath);
            this.source("suffix", this.suffix);
        },
        setContextPath : function(){
            var scripts = document.getElementsByTagName("script");
            var size = scripts.length;
            var src = "";
            var p = /(\/smart)([-_]min)?\.js(\?.*)?/;
            
            for(var i = 0; i < size; i++){
                src = scripts[i].src;
                if(p.test(src)){
                    this.contextPath = src.replace(p, "/");
                    this.suffix = (RegExp.$2||"");
                    break;
                }
            }
        },
        /**
         * 调用模块方法
         * @param String args... 动态参数
         * @param Function callback 回调处理函数
         * @throw Error
         */
        use : function(){
            var args = arguments;
            var size = args.length;
            var modules = [];
            var callback = null;
            
            if(size < 2){
                throw new Error("Smart().use(args...)::参数长度错误，length = " + size);
            }
            
            callback = args[size - 1];
            
            if((callback instanceof Function) && callback.apply){
                if("Modules" in Smart){
                    modules = _requires(args);
                    _queue.add.apply(_queue, modules);
                    _queue.load(callback);
                }else{
                    _queue.add("module").load(function(){
                        Smart.use.apply(Smart, args);
                    });
                }
            }else{
                throw new Error("Smart().use(args...)::未知的回调函数，callback : " + typeof(callback));
            }
            
        },
        /**
         * 登记注册定义的模块
         * @param String namespace 命名空间
         * @param Object o 对象
         */
        source : function(namespace, o){
            Smart[namespace] = o;
        },
        /**
         * 添加模块
         * @param String module 模块名
         * @param Funcion callback 模块实现方法
         * @param Object conf 配置
         */
        define : function(module, callback){
            callback.apply(Smart, [Smart]);
        }        
    };
    
    /**
     * 全局Smart命名空间对象
     */
    var Smart = window["Smart"]  = function(){
        var args = arguments;
        var S = this;
        
        if(!(S instanceof Smart)){
            S = new Smart();            
            S.init();            
        }
        return S;
        
    };
    
    for(var p in proto){
        if(proto.hasOwnProperty(p)){
            Smart[p] = proto[p];
        }
    }
    
    Smart.prototype = proto;
    Smart.Queue = Queue;
    
    var _queue = new Queue();
})("1.0a");